;(function() {
	
	var LOCATION_SERVICE = null;
	
	Nokia.GBCLocation = {
		
		/*
		 * Detects the user's location by using Platform Services 1.0
		 */
		locateDeviceLocation: function(_callback)
		{
			if(LOCATION_SERVICE == null)
			{
				LOCATION_SERVICE = device.getServiceObject("Service.Location", "ILocation");
			}
			
			var self = this;
			
			// Use a longer timeout interval to prevent timeouts in closed environments
			
			var updateoptions = new Object();
			updateoptions.PartialUpdates = false;
			updateoptions.UpdateTimeOut = 120000000;
			
			var criteria = new Object();
			criteria.LocationInformationClass = 'BasicLocationInformation';
			criteria.Updateoptions = updateoptions;
			
			// Calls the asynchronous GetLocation method from Location API
			
			LOCATION_SERVICE.ILocation.GetLocation(criteria, function(transId, eventCode, result)
			{
				self.locationHandler(transId, eventCode, result, _callback);
			});
		},
		
		/*
		 * Callback for the Location API GetLocation method
		 */
		locationHandler: function(transId, eventCode, result, _callback)
		{
			// Check if no error occurred during the Platform Services call
			if(eventCode != 4)
			{
				var detectedLocation = {
					'latitude': result.ReturnValue.Latitude,
					'longitude': result.ReturnValue.Longitude
				};
				
				// Calling the reverse geocode function to retrieve the location name
				
				this.reverseGeocode(detectedLocation, _callback);
			}
			else
			{
				_callback(result.ErrorCode, result.ErrorMessage, null);
			}
		},
		
		/*
		 * Geocodes any address, retrieving the associated latitude and longitude coordinates
		 * Geocoding is performed by using the Geonames web services
		 */
		geocodeLocation: function(_address, _callback)
		{
			var instance = this;
			
			var url = 'http://ws.geonames.org/searchJSON?q=' + escape(_address) + '&maxRows=1';
			
			try {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
			} catch (e) {};
			
			var ajaxParams = {
				url : url,
				dataType: 'json',
				type: 'GET',
				success: function(data) {					
					instance.geocodeLocationSuccess(data, _callback);
				},
				error: function(data) {	
					instance.geocodeLocationError(data, _callback);
				}
			};
			
			jQuery.ajax(ajaxParams);
		},
		
		/*
		 * Success callback for the geocode XMLHttpRequest
		 */
		geocodeLocationSuccess: function(data, _callback)
		{
			var results = data.geonames;
			
			// Checks if any results are returned...
			if(results.length > 0)
			{
				// ...and picks the first one
				var geocodedLocation = {
					'latitude': results[0].lat,
					'longitude': results[0].lng
				};
				
				// Calls the reverse geocode function to retrieve the location name
		
				this.reverseGeocode(geocodedLocation, _callback);
			}
			else
			{
				_callback(-2, "No Locations Found", null);
			}
		},
		
		/*
		 * Error callback for the geocode XMLHttpRequest
		 */
		geocodeLocationError: function(data, _callback)
		{
			_callback(-1, "Network Error", null);
		},
		
		/*
		 * Performs reverse geocoding of a given location, 
		 * using the geonames Web services
		 */
		reverseGeocode: function(location, _callback)
		{
			var url = 'http://ws.geonames.org/findNearbyPlaceNameJSON?lat=' + location.latitude + '&lng=' + location.longitude;
			
			var instance = this;
			
			try {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
			} catch (e) {};
			
			var ajaxParams = {
				url : url,
				type: 'GET',
				dataType: 'json',
				success: function(data) {					
					instance.reverseGeocodeSuccess(data, _callback, location);
				},
				error: function(data) {	
					instance.reverseGeocodeError(data, _callback, location);
				}
			};
			
			jQuery.ajax(ajaxParams);
		},
		
		/*
		 * Success callback for the reverse geocoding XMLHttpRequest
		 */
		reverseGeocodeSuccess: function(data, _callback, location)
		{
			var results = data.geonames;
			
			// Check if any results are returned...
			if(results.length > 0)
			{
				// ...and pick the first one
				location.name = results[0].name;
				
				_callback(0, null, location);
			}
			else
			{
				_callback(-4, "Reverse Geocoder failed to identify location");
			}
		},
		
		/*
		 * Error callback for the reverse geocoding XMLHttpRequest
		 */
		reverseGeocodeError: function(data, _callback, location)
		{
			_callback(-3, "Reverse Geocoder network error", null);
		}
	};
})();